/*
 * File		: cym_list.h
 * Version	: 0.1.0
 * Author	: Vincent Cheung
 * Date		: Sept. 23, 2013
 * Description	: The head file of cym_list.c.
 * 
 * Change Logs  : 
 * Date                 Author          Notes
 * Sept. 23, 2013       Vincent         first version
 *
 */

#ifndef	__CYM_LIST_H__
#define	__CYM_LIST_H__

#include "cym_def.h"

/**
 * @addtogroup Kernel
 */

/*@{*/

/**
 * initialize a list object
 */
#define CYM_LIST_OBJECT_INIT(list) {&(list), &(list)}

/**
 * to get the entry of structure
 */
#ifdef CYM_USING_16BIT_CPU
#define CYM_LIST_ENTRY(node, type, member) \
        ((type *)((char *)(node) - (unsigned int)(&((type *)0)->member)))
#else
#define CYM_LIST_ENTRY(node, type, member) \
        ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))
#endif
/*@}*/

#ifdef CYM_USING_INLINE

#pragma inline cym_list_init, cym_list_insert_after, cym_list_insert_before, \
        cym_list_remove, cym_list_is_empty

/**
 * This function is used to initialize a list.
 *
 * @param list a list to be initialized
 *
 * @retval NULL
 */
void cym_list_init(list_t *list)
{
	list->next = list->prev = list;
}

/**
 * This function is used to insert a new node after a list.
 *
 * @param list list to insert into it
 * @param node a new node to be inserted
 *
 * @retval NULL
 */
void cym_list_insert_after(list_t *list, list_t *node)
{
	list->next->prev = node;
	node->next = list->next;

	list->next = node;
	node->prev = list;
}

/**
 * This function is used to insert a new node before a list.
 *
 * @param list a list to insert into it
 * @param node a new node to be inserted
 *
 * @retval NULL
 */
void cym_list_insert_before(list_t *list, list_t *node)
{
	list->prev->next = node;
	node->prev = list->prev;

	list->prev = node;
	node->next = list;
}

/**
 * This function is used to remove a node from a list.
 *
 * @param node the node to remove from the list
 *
 * @retval NULL
 */
void cym_list_remove(list_t *node)
{
	node->next->prev = node->prev;
	node->prev->next = node->next;

	node->next = node->prev = node;
}

/**
 * This function is used to check whether the list is empty.
 *
 * @param list the list to be checked
 *
 * @return return CYM_TRUE if the list is empty
 */
bool_t cym_list_is_empty(const list_t *list)
{
	if (list->next == list)
	{
		return CYM_TRUE;
	}

	return CYM_FALSE;
}

#else

void cym_list_init(list_t *list);
void cym_list_insert_after(list_t *list, list_t *node);
void cym_list_insert_before(list_t *list, list_t *node);
void cym_list_remove(list_t *node);
bool_t cym_list_is_empty(const list_t *list);

#endif	/* CYM_USING_INLINE */

#endif	/* __CYM_LIST_H__ */